<html>
  <head>
	  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>i5ting_ztree_toc:vuex</title>
		<link href="toc/style/github-bf51422f4bb36427d391e4b75a1daa083c2d840e.css" media="all" rel="stylesheet" type="text/css"/>
		<link href="toc/style/github2-d731afd4f624c99a4b19ad69f3083cd6d02b81d5.css" media="all" rel="stylesheet" type="text/css"/>
		<link href="toc/css/zTreeStyle/zTreeStyle.css" media="all" rel="stylesheet" type="text/css"/>
	  <style>
		pre {
		    counter-reset: line-numbering;
		    border: solid 1px #d9d9d9;
		    border-radius: 0;
		    background: #fff;
		    padding: 0;
		    line-height: 23px;
		    margin-bottom: 30px;
		    white-space: pre;
		    overflow-x: auto;
		    word-break: inherit;
		    word-wrap: inherit;
		}

		pre a::before {
		  content: counter(line-numbering);
		  counter-increment: line-numbering;
		  padding-right: 1em; /* space after numbers */
		  width: 25px;
		  text-align: right;
		  opacity: 0.7;
		  display: inline-block;
		  color: #aaa;
		  background: #eee;
		  margin-right: 16px;
		  padding: 2px 10px;
		  font-size: 13px;
		  -webkit-touch-callout: none;
		  -webkit-user-select: none;
		  -khtml-user-select: none;
		  -moz-user-select: none;
		  -ms-user-select: none;
		  user-select: none;
		}

		pre a:first-of-type::before {
		  padding-top: 10px;
		}

		pre a:last-of-type::before {
		  padding-bottom: 10px;
		}

		pre a:only-of-type::before {
		  padding: 10px;
		}

		.highlight { background-color: #ffffcc } /* RIGHT */
		</style>
  </head>
  <body>
	  <div>
				<div style='width:25%;'>
						<ul id="tree" class="ztree" style='width:100%'>

						</ul>
				</div>
        <div id='readme' style='width:70%;margin-left:20%;'>
          	<article class='markdown-body'>
            	<h2 id="vuex-">Vuex-基本介绍</h2>
<h3 id="-">目标</h3>
<ul>
<li>掌握什么是vuex</li>
<li>了解vuex解决的问题</li>
</ul>
<h3 id="-">问题导入</h3>
<p>观察下图中的效果： 修改头像之后，左侧菜单和右上角的头像都会跟着变化。</p>
<p><img src="asset/vuex使用场景.gif"  /></p>
<p>抽象一下这个问题：</p>
<p><img src="asset/image-20210601103033022.png" alt="image-20210601103033022" style="zoom:50%;" /></p>
<p>思考，如何实现一处数据的修改能同步到其他的组件？</p>
<h3 id="-">回顾组件关系和通信方案</h3>
<p><img src="asset/image-20210323175925844.png" alt="image-20210323175925844"></p>
<table>
<thead>
<tr>
<th>序号</th>
<th>组件关系</th>
<th>数据通信</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>父子关系</td>
<td>子传父：props ； 父传子：$emit</td>
</tr>
<tr>
<td>2</td>
<td>非父子关系</td>
<td>eventBus:   $on  +  $emit</td>
</tr>
<tr>
<td><strong>3</strong></td>
<td><strong>非父子关系</strong></td>
<td><strong>vuex</strong></td>
</tr>
</tbody>
</table>
<p>和我们已经学过的父子通信和兄弟通信类似，vuex也是一种组件通信解决方案</p>
<h3 id="vuex-">Vuex是什么</h3>
<p><a href="https://vuex.vuejs.org/zh/">Vuex</a> 是一个专为 Vue.js 应用程序开发的<strong>状态管理模式</strong>， 采用<strong>集中式存储</strong>管理应用的所有组件的状态，解决多组件数据通信。</p>
<p>要点：</p>
<ol>
<li>vue官方搭配，专属使用 (类似于：vue-router)，有专门的调试工具</li>
<li><strong>集中式</strong>管理数据状态方案 (操作更简洁)<code>data() { return { 数据, 状态 }}</code></li>
<li>数据变化是可预测的 (<strong>响应式</strong>)</li>
</ol>
<p>vue官方提供的独立于组件体系之外的，管理公共数据的工具</p>
<p><img src="asset/image-20210601212946879.png" alt="image-20210601212946879"></p>
<h3 id="-">使用场景</h3>
<p>大型项目</p>
<h3 id="-">小结</h3>
<p>vuex是vue官方提供的独立于组件体系之外的，管理公共数据的工具</p>
<h2 id="vuex-">Vuex-学习内容</h2>
<h3 id="-">目标</h3>
<p>了解vuex的学习内容</p>
<h3 id="vuex-">Vuex的学习内容</h3>
<p>Vuex中有5个内容需要学习：</p>
<ol>
<li><strong>state</strong>： 统一定义公共数据（类似于data(){return {a:1, b:2，xxxxxx}}）</li>
<li><strong>mutations</strong> ： 使用它来修改数据(类似于methods)</li>
<li>getters： 类似于computed(计算属性，对现有的状态进行计算得到新的数据-------派生  )</li>
<li>actions： 发起异步请求</li>
<li>modules： 模块拆分</li>
</ol>
<p>其中最为重要的内容是state和mutations</p>
<p><img src="asset/image-20210601215035990.png" alt="image-20210601215035990" style="zoom: 67%;" /></p>
<h3 id="-">小结</h3>
<p>五个概念：state,  mutations,  getters, actions, modules</p>
<h2 id="vuex-vue-vuex">Vuex-在Vue项目使用Vuex</h2>
<h3 id="-">目标</h3>
<p>掌握在vue项目中使用vuex的方式</p>
<h3 id="-">两种情况</h3>
<ol>
<li><p>情况1：在老项目中使用。 先额外安装vuex包，然后在配置。</p>
</li>
<li><p>情况2：在新项目中使用。 在配置vue-cli中创建项目时，就可以直接选中vuex项，这样就不用做任何配置了（脚手架会自动帮我们完成的）。具体如下图示：</p>
</li>
</ol>
<p><img src="asset/在脚手架工具中选中vuex.gif"  /></p>
<p>这里只说明第1种情况。</p>
<h3 id="-vuex">在旧项目中使用vuex</h3>
<blockquote>
<p>假设之前已经有一个vue项目了，其中并没有使用vuex，现在我们来用一下。 </p>
<p>注意，这里省略用vue脚手架创建项目的过程。</p>
</blockquote>
<p>整体步骤：</p>
<ol>
<li>安装。它是一个独立的包，需要先安装。</li>
<li>配置<ol>
<li>创建Vuex.store实例</li>
<li>向Vue实例注入store</li>
</ol>
</li>
<li>使用。在组件中使用store</li>
</ol>
<h4 id="-">安装包</h4>
<p>进入项目目录，安装包</p>
<p> <code>npm install vuex</code></p>
<blockquote>
<p>开发依赖 ： npm i xxxx --save-dev ;  npm i xxxx -D ;</p>
<p>生产依赖： npm i xxxx --save ;            npm i xxxx -S;     npm i xxxx</p>
</blockquote>
<h4 id="-store">实例化store</h4>
<p>与router一样，当我们在项目中使用vuex之后，为了方便代码维护，我们一般需要做特殊的目录调整，约定的结构如下：</p>
<pre><code>|--src
|----- main.js
|----- store
|----------- index.js
</code></pre><p>在store/index.js 中放置具体的代码，具体如下：</p>
<pre><code class="lang-js">import Vue from &#39;vue&#39;
import Vuex from &#39;vuex&#39;

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  }
})
export default store
</code></pre>
<h4 id="-vue-store">向Vue实例注入store</h4>
<p>在src/main.js中：</p>
<ol>
<li>导入store</li>
<li>并注入Vue实例</li>
</ol>
<pre><code class="lang-js">// 省略其他
// 1. 导入store
import store from &#39;./store&#39; 

new Vue({
  // 省略其他...
  store // 2. 注入Vue实例
})
</code></pre>
<h4 id="-store">在组件中使用store</h4>
<p>在任意组件中，通过<code>this.$store.state</code> 来获取公共数据。</p>
<h3 id="-">小结</h3>
<p>在老项目中使用vuex的步骤</p>
<ol>
<li>安装。它是一个独立的包，需要先安装。</li>
<li>配置<ol>
<li>创建Vuex.store实例(有固定代码，类似于vue-router；需要记忆)</li>
<li>向Vue实例注入store</li>
</ol>
</li>
<li>使用。在组件中使用store。<code>this.$store.state</code></li>
</ol>
<hr>
<p>附 ：vue-router的使用方式</p>
<p><strong>目录结构</strong></p>
<pre><code class="lang-bash">|- router # 路由
|------ index.js
|- main.js # 项目入口文件
</code></pre>
<p><strong>关键代码</strong></p>
<pre><code class="lang-js">// router/index.js

import Vue from &#39;vue&#39;
import Router from &#39;vue-router&#39;

Vue.use(Router)

// 默认导出 export defalut
export default new Router({
  routes: []
})
</code></pre>
<h2 id="vuex-state-">Vuex-state定义公共数据并在组件中使用</h2>
<h3 id="-">目标</h3>
<p>掌握state的使用方式</p>
<h3 id="state-">state的作用</h3>
<p>vuex用它来保存公共数据</p>
<h3 id="-">定义公共数据</h3>
<p>格式</p>
<pre><code class="lang-js">new Vuex.store({
  state: {
   属性名： 属性值 
  }
})
</code></pre>
<p>示例</p>
<pre><code class="lang-js">new Vuex.store({
  state: {
    userInfo: {
       name: &#39;tom&#39;,
            skills: [&#39;抖音&#39;, &#39;B站&#39;, &#39;美团&#39;],
         address: &#39;武汉黑马&#39;,
       logo: &#39;https://vuejs.org/images/logo.svg&#39;
       //  https://www.runoob.com/wp-content/uploads/2016/02/react.png
    }
  }
})

</code></pre>
<h3 id="-">使用公共数据</h3>
<p>格式：</p>
<p><strong>在组件中</strong>，通过<code>this.$store.state.属性名</code>来访问。</p>
<p><strong>在模板中</strong>，则可以省略<code>this</code>而直接写成： <code>{{$store.state.属性名}}</code></p>
<p><img src="asset/image-20210601210940718.png" alt="image-20210601210940718"></p>
<h3 id="vue-devtool-">vue-devtool调试工具</h3>
<p>在调试工具中查看。</p>
<p><img src="asset/image-20210603101500328.png" alt="image-20210603101500328"></p>
<h3 id="-">小结</h3>
<p>state的作用是：保存公共数据（多组件中共用的数据）</p>
<p>state是响应式的： 如果修改了数据，相应的在视图上的值也会变化。</p>
<h2 id="vuex-mutations-">Vuex-用mutations修改公共数据</h2>
<h3 id="-">目标</h3>
<p>掌握mutations的作用及格式； 能用它来修改state</p>
<h3 id="-">作用</h3>
<p>通过调用mutations来修改定义在state中的公共数据。</p>
<p><img src="./asset/image-20210601121840170.png" alt="image-20210601121840170" style="zoom: 80%;" /></p>
<h3 id="-">格式</h3>
<p>分两个格式： 注册的格式，调用的格式</p>
<p><strong>定义格式</strong>： 如下</p>
<pre><code class="lang-js">new Vue.store({
  // 省略其他...
  mutations：{
    // 每一项都是一个函数，可以声明两个形参
      mutation名1：function(state [, 载荷]) {

    },
    mutation名2：function(state [, 载荷]) {

    },
    }
})
</code></pre>
<p>每一项都是一个函数，可以声明两个形参：</p>
<ul>
<li>第一个参数是必须的，表示当前的state。在使用时不需要传入</li>
<li>第二个参数是可选的，表示载荷，是可选的。在使用时要传入的数据</li>
</ul>
<p><strong>使用格式</strong></p>
<pre><code class="lang-js">this.$store.commit(&#39;mutation名&#39;, 实参，给第二个参数)
</code></pre>
<p>这里的commit是固定的方法</p>
<h3 id="-">示例</h3>
<p>在<code>store/index.js</code>中，补充：</p>
<ul>
<li>数据项url</li>
<li>更新数据项url的mutations</li>
</ul>
<pre><code class="lang-js">export default new Vuex.Store({
  // state: 用来保存所有的公共数据
  state: {
    userInfo: {
       name: &#39;tom&#39;,
            skills: [&#39;抖音&#39;, &#39;B站&#39;, &#39;美团&#39;],
         address: &#39;武汉黑马&#39;,
       logo: &#39;https://vuejs.org/images/logo.svg&#39;
       //  https://www.runoob.com/wp-content/uploads/2016/02/react.png
    }
  },
  // mutations: 用它提供修改数据的方法
  //   中文是：变化，异动。
  //   数据不应该在组件内部直接修改，必须在组件内调用mutations来修改
  mutations: {
    setLogo(state, newUrl) {
      state.userInfo.logo = newUrl
    }
  }
}
</code></pre>
<p>在组件中，调用</p>
<pre><code class="lang-js">const url = &#39;http://s02.mifile.cn/assets/static/image/logo-mi2.png&#39;
this.$store.commit(&#39;changeUrl&#39;, url)
</code></pre>
<p><strong>图示</strong></p>
<p><img src="asset/image-20210928104236863.png" alt="image-20210928104236863"></p>
<h3 id="-devtool-">在devtool中观察</h3>
<p>打开调试工具，查看效果</p>
<h3 id="-">小结</h3>
<p>mutations的中文含义是：变异。 它是Vuex中用来<strong>修改公共数据</strong>的唯一入口。</p>
<p>在定义时：</p>
<ul>
<li>它的第一个参数是state，第二个参数是载荷</li>
</ul>
<p>在调用时：</p>
<ul>
<li>用 this.$store.<strong>commit</strong>(&#39;mutation名&#39;， 载荷) 来调用</li>
</ul>
<h2 id="vuex-mutaions-">Vuex-mutaions拓展理解</h2>
<p>问：为啥是<code>$store.commit(&#39;mutations的名字&#39;)</code>而不是$store.mutations的名字()?</p>
<p>答：Vuex 中的 mutation 非常类似于事件：每个 mutation 都有一个字符串的 <strong>事件类型 (type)</strong> 和 一个 <strong>回调函数 (handler)</strong>。这个回调函数就是我们实际进行状态更改的地方，并且它会接受 state 作为第一个参数。</p>
<p>问：数据不可以该在组件内部直接修改吗？</p>
<p>答：不能。虽然语法上不报错，也有响应式的特点。但是不推荐。特别是在严格模式下会报错。<code>若将vue创建 store 的时候传入 strict: true, 开启严格模式,那么任何修改state的操作，只要不经过 mutation的函数，vue就会报错</code></p>
<p>问：可以传递多个数据吗？</p>
<p>答：参数只能有一个：下面的写法是不对的：</p>
<pre><code class="lang-bash">this.$store.commit(&#39;setUrl&#39;, url, host) // host这个参数将无法被接收到 
</code></pre>
<p>如果希望传递复杂的数据，第二个参数可以是对象，例如下面的写法</p>
<pre><code class="lang-bash">this.$store.commit(&#39;setUrl&#39;, { url, host} )
</code></pre>
<p>问：等价写法 <code>this.$store.comit({type: &#39;mutations的名字&#39;})</code></p>
<h2 id="-">小案例-发请求取数据做保存</h2>
<h3 id="-">目标</h3>
<p>综合使用axios, mutation, state</p>
<h3 id="-">任务描述</h3>
<p>我们希望在某组件创建成功之后：</p>
<ol>
<li>请求后端接口（<a href="https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books）处获取数据">https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books）处获取数据</a></li>
<li>保存数据到state中</li>
</ol>
<h3 id="-">思路</h3>
<p>组件created钩子函数中：</p>
<ul>
<li>发ajax请求(用axios库)，获取数据</li>
<li>调用mutations保存数据到vuex</li>
<li>在组件中使用数据</li>
</ul>
<h3 id="-">代码</h3>
<p>在<code>app.vue</code>（或者其他的组件）中，created钩子函数中的代码如下：</p>
<pre><code class="lang-js">created() {
  axios({
        url: &#39;https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books&#39;,
        method: &#39;GET&#39;
      }).then(res =&gt; {
        console.log(res)
        this.$store.commit(&#39;setBooks&#39;, res.data.data)
      })
}
</code></pre>
<p>在<code>src/store/index.js</code>中，补充对应的数据项 books和操作的方法。</p>
<pre><code class="lang-js">state: {
  // 省略其他...
  books: [] // 用来保存书
},
mutations: {
  // 省略其他...

  // 用来设置数据
  setBooks(state, books) {
     state.books = books
  }
}
</code></pre>
<p><code>app.vue</code>模板中 渲染数据</p>
<pre><code class="lang-vue">&lt;div style=&quot;flex: 1 1 auto; border:1px solid #ccc;&quot;&gt;
        书目
        &lt;p v-for=&quot;(book, idx) in $store.state.books&quot; :key=&quot;idx&quot;&gt;
          {{book.name}}, {{book.price}}
        &lt;/p&gt;
            总价为：XX元
      &lt;/div&gt;
</code></pre>
<h3 id="-">小结</h3>
<p><img src="asset/image-20210927115530792.png" alt="image-20210927115530792"></p>
<h2 id="vuex-getters-">Vuex-用getters的派生状态</h2>
<h3 id="-">目标</h3>
<p>了解getters的作用； 掌握它的用法；</p>
<h3 id="-">作用</h3>
<p>在state中的数据的基础上，进一步对数据进行加工得到新数据。(与组件中computed一样)</p>
<p>例如：计算总价</p>
<pre><code class="lang-js">new Vuex.store({
  state: {
    books: [
      {
        &quot;name&quot;: &quot;javasript技术内幕&quot;,
        &quot;price&quot;: 100,
        &quot;img&quot;: &quot;https://img3m7.ddimg.cn/64/26/29120617-1_u_8.jpg&quot;
      },
      {
        &quot;name&quot;: &quot;数学之美&quot;,
        &quot;price&quot;: 44,
        &quot;img&quot;: &quot;https://img3m2.ddimg.cn/18/30/28538352-1_b_5.jpg&quot;
      },
      {
        &quot;name&quot;: &quot;认知天性&quot;,
        &quot;price&quot;: 40,
        &quot;img&quot;: &quot;https://img3m3.ddimg.cn/74/33/1732997153-3_u_3.jpg&quot;
      }
    ]
  }
})
</code></pre>
<h3 id="-">定义格式</h3>
<pre><code class="lang-js">new Vuex.store({
  // 省略其他...
  getters: {
    // state 就是上边定义的公共数据state
    getter的名字1: function(state) {
      return 要返回的值
    }
  }
})
</code></pre>
<p>state 就是上边定义的公共数据state</p>
<h3 id="-">使用格式</h3>
<p>在组件中通过：<code>$store.getters.getter的名字</code> 来访问</p>
<h3 id="-">在调试工具中查看</h3>
<h3 id="-">小结</h3>
<p>它的作用是从已有公共数据项中派生出新的数据项，类似于computed</p>
<h2 id="vuex-state-mutation-getters-">Vuex-state-mutation-getters 小结</h2>
<p>vuex维护公共数据，主要有两个动作：</p>
<ol>
<li>定义数据: </li>
<li>提供<strong>获取/修改</strong>数据的方法</li>
</ol>
<p><img src="asset/image-20210927114822586.png" alt="image-20210927114822586"></p>
<h2 id="vuex-actions-">Vuex用actions发异步请求</h2>
<h3 id="-">目标</h3>
<p>掌握actions的使用</p>
<h3 id="-">作用</h3>
<p>我们可以使用Action来修改state，这一点是类似于 mutation的，不同在于：</p>
<ul>
<li>action中可以通过调用 mutation来修改state，而不是直接变更状态。</li>
<li>action 可以包含<strong>任意异步</strong>(例如ajax请求)操作。</li>
</ul>
<h3 id="-">定义格式</h3>
<pre><code class="lang-js">new Vuex.store({
  // 省略其他...
  actions: {
    // context对象会自动传入，它与store实例具有相同的方法和属性
    action的名字: function(context, 载荷) {
      // 1. 发异步请求, 请求数据

      // 2. commit调用mutation来修改/保存数据

      // context.commit(&#39;mutation名&#39;, 载荷)
    }
  }
})
</code></pre>
<h3 id="-">调用格式</h3>
<p>在组件中通过<code>this.$store.dispatch(&#39;actions的名字&#39;, 参数)</code>来调用action</p>
<h3 id="-">代码示例</h3>
<p>修改上面例子中的发请求图书的代码，将axios的部分写到action中</p>
<pre><code class="lang-js">// 发ajax请求，从后端获取数据，再来去修改state中的数据
    actions: {
      getBooks (context, params) {
        console.log(&#39;getbooks的查询参数是&#39;, params)
        axios({
          url: &#39;https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books&#39;,
          method: &#39;GET&#39;
        }).then(res =&gt; {
          console.log(res)
          context.commit(&#39;setBooks&#39;, res.data.data)
        })
      }
    },
</code></pre>
<h3 id="-">小结</h3>
<p>action一般用来发异步请求，数据回来之后，在去调用mutations来保存数据</p>
<p><img src="asset/image-20210927115932890.png" alt="image-20210927115932890"></p>
<p>将ajax请求放在actions中有两个好处：</p>
<ol>
<li>代码得到了进一步封装。将发ajax和保存数据到vuex绑定在一起。</li>
<li>逻辑更通顺。如果数据需要保存在Vuex的state中，那从接口处获取数据的操作就定义在Vuex的actions中。</li>
</ol>
<h2 id="vuex-modules-">Vuex-用modules来拆分复杂业务</h2>
<h3 id="-">问题导入</h3>
<p>随着项目越来越大，需要放在vuex中的数据越来越多，整个store/index.js中代码会越来越长，怎么办呢？</p>
<h3 id="modules-">modules的作用</h3>
<p>拆分模板，把复杂的场景按模块来拆开</p>
<h3 id="-">格式</h3>
<pre><code class="lang-js">export default new Vuex.Store({
  // state: 用来保存所有的公共数据
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {
      模块名1： {
            // namespaced为true，则在使用mutations时，就必须要加上模块名
          namespaced: true, 
            state: {},
              getters: {},
              mutations: {},
              actions: {},
              modules: {}
      }，
    模块名2： {
        // namespaced不写，默认为false，则在使用mutations时，不需要加模块名
            state: {},
              getters: {},
              mutations: {},
              actions: {},
         modules: {}
      }  
  }
})

</code></pre>
<p>也可以更进一步对文件进行拆分。</p>
<pre><code>|--store /
|------- index.js # 引入模块
|------- modules
|-------------- / mod1.js # 模块1
|-------------- / mod2.js # 模块2
</code></pre><h3 id="-">访问数据和修改数据的调整</h3>
<ul>
<li><p>访问模块中的数据，要加上模块名</p>
<pre><code>获取数据项：  {{$store.state.模块名.数据项名}}
获取getters： {{$store.getters[&#39;模块名/getters名&#39;]}}
</code></pre></li>
<li><p>访问模块中的mutations/actions:  </p>
<ul>
<li>如果namespaced为true，则需要额外去补充模块名</li>
<li>如果namespaced为false，则不需要额外补充模块名</li>
</ul>
<pre><code class="lang-js">$store.commit(&#39;mutations名&#39;)        // namespaced为false
$store.commit(&#39;模块名/mutations名&#39;)  // namespaced为true
</code></pre>
</li>
</ul>
<h3 id="-">小结</h3>
<p>使用了modules之后，在访问数据时就要额外添加modules的名字了。</p>
<p>结论： 在使用modules时，建议都给加上namespaced!</p>
<h2 id="vuex-modules-">vuex-用modules之后代码结构优化</h2>
<p><img src="asset/image-20210603155218649.png" alt="image-20210603155218649"></p>
<h2 id="vuex-mapstate-">Vuex-辅助函数mapState来使用公共数据</h2>
<h3 id="-">目标</h3>
<p>掌握mapState的用法，将state中的变量映射到当前的组件中使用； </p>
<h3 id="-">问题</h3>
<p>当访问某个数据项嵌套太深了，能不能优化一下访问的方式？</p>
<p>用mapState把公共数据（vuex.store） 映射 到本组件内部的<strong>计算属性</strong>中</p>
<h3 id="mapstate-">mapState的使用步骤</h3>
<h4 id="-">映射</h4>
<pre><code class="lang-js">// 1. 导入辅助函数mapState，它是在vuex中定义的一个工具函数。
//  es6 按需导入 import { mapState } from &#39;vuex&#39; 
import { mapState } from &#39;vuex&#39;

computed: {
   // 说明1： ...对象 是把对象展开，合并到computed
   // 说明2： mapState是一个函数 
   //  [&#39;数据项1&#39;， &#39;数据项2&#39;]
   ...mapState([&#39;xxx&#39;])，
   ...mapState({&#39;新名字&#39;: &#39;xxx&#39;})
}
</code></pre>
<h4 id="-">使用</h4>
<pre><code>this.xxx
{{xxx}}
</code></pre><h3 id="-">示例</h3>
<pre><code class="lang-js">// 步骤
// 1. 导入辅助函数mapState，它是在vuex中定义的一个工具函数。
//  es6 按需导入 import { mapState } from &#39;vuex&#39; 
import { mapState } from &#39;vuex&#39;

// 2. 在computed中使用 ...mapState([&#39;books&#39;])
// const res = mapState([&#39;books&#39;])
// res的结果是一个对象： { books: function() {}}
// console.log(&#39;mapState&#39;, res)

export default {
  computed: {
    c1 () {
      return &#39;c1&#39;
    },
    // books: function() {}
    // ..res： 把res这个对象合并到computed对象中
    // ...res
    ...mapState([&#39;books&#39;])
  }
}
&lt;/script&gt;
</code></pre>
<h3 id="-">小结</h3>
<ol>
<li>mapState是辅助函数，将vuex中的数据投射到组件内部；</li>
<li>computed:{ ...mapState() } 这里的...是对象的展开运算符，整体来看是对象的合并。</li>
</ol>
<h2 id="vuex-mapstate-">Vuex-辅助函数mapState对数据重命名</h2>
<h3 id="-">目标</h3>
<p>掌握mapState对数据重命名的用法。</p>
<h3 id="-">场景</h3>
<p>vuex中的数据与本组件内的数据名相同</p>
<h3 id="-">格式</h3>
<pre><code>...mapState({&#39;新名字&#39;: &#39;xxx&#39;})
</code></pre><h2 id="vuex-map-">Vuex-map函数用法汇总</h2>
<p><img src="asset/image-20210602203233284.png" alt="image-20210602203233284" style="zoom:50%;" /></p>
<h3 id="-state">如何使用全局state</h3>
<ul>
<li><p>直接使用： this.$store.state.xxx; </p>
</li>
<li><p>map辅助函数：</p>
<pre><code class="lang-js">computed: { 
  ...mapState([&#39;xxx&#39;]), 
  ...mapState({&#39;新名字&#39;: &#39;xxx&#39;})
}
</code></pre>
</li>
</ul>
<h3 id="-modules-state">如何使用modules中的state</h3>
<ul>
<li><p>直接使用： this.$store.state.模块名.xxx; </p>
</li>
<li><p>map辅助函数：</p>
<pre><code class="lang-js">computed: { 
  ...mapState(&#39;模块名&#39;, [&#39;xxx&#39;]), 
  ...mapState(&#39;模块名&#39;, {&#39;新名字&#39;: &#39;xxx&#39;})
}
</code></pre>
</li>
</ul>
<h3 id="-getters">如何使用全局getters</h3>
<ul>
<li><p>直接使用：<code>this.$store.getters.xxx</code></p>
</li>
<li><p>map辅助函数：</p>
<pre><code class="lang-js">computed: { 
  ...mapGetters([&#39;xxx&#39;]), 
  ...mapGetters({&#39;新名字&#39;: &#39;xxx&#39;})
}
</code></pre>
</li>
</ul>
<h3 id="-modules-getters">如何使用modules中的getters</h3>
<ul>
<li><p>直接使用： <code>this.$store.getters.模块名.xxx</code></p>
</li>
<li><p>map辅助函数：</p>
<pre><code class="lang-js">computed: { 
  ...mapGetters(&#39;模块名&#39;, [&#39;xxx&#39;]), 
  ...mapGetters(&#39;模块名&#39;,{&#39;新名字&#39;: &#39;xxx&#39;})
}
</code></pre>
</li>
</ul>
<h3 id="-mutations">如何使用全局mutations</h3>
<ul>
<li><p>直接使用：<code>this.$store.commit(&#39;mutation名&#39;, 参数)</code></p>
</li>
<li><p>map辅助函数：</p>
<pre><code class="lang-js">methods: { 
  ...mapMutations([&#39;mutation名&#39;]), 
  ...mapMutations({&#39;新名字&#39;: &#39;mutation名&#39;})
}
</code></pre>
</li>
</ul>
<h3 id="-modules-mutations-namespaced-true-">如何使用modules中的mutations（namespaced:true）</h3>
<ul>
<li><p>直接使用： <code>this.$store.commit(&#39;模块名/mutation名&#39;, 参数)</code></p>
</li>
<li><p>map辅助函数：</p>
<pre><code class="lang-js">methods: { 
  ...mapMutations(&#39;模块名&#39;, [&#39;xxx&#39;]), 
  ...mapMutations(&#39;模块名&#39;,{&#39;新名字&#39;: &#39;xxx&#39;})
}
</code></pre>
</li>
</ul>
<h3 id="-actions">如何使用全局actions</h3>
<ul>
<li><p>直接使用：<code>this.$store.dispatch(&#39;action名&#39;, 参数)</code></p>
</li>
<li><p>map辅助函数：</p>
<pre><code class="lang-js">methods: { 
  ...mapActions([&#39;actions名&#39;]), 
  ...mapActions({&#39;新名字&#39;: &#39;actions名&#39;})
}
</code></pre>
</li>
</ul>
<h3 id="-modules-actions-namespaced-true-">如何使用modules中的actions（namespaced:true）</h3>
<ul>
<li><p>直接使用： <code>this.$store.dispatch(&#39;模块名/action名&#39;, 参数)</code></p>
</li>
<li><p>map辅助函数：</p>
<pre><code class="lang-js">methods: { 
  ...mapActions(&#39;模块名&#39;, [&#39;xxx&#39;]), 
  ...mapActions(&#39;模块名&#39;,{&#39;新名字&#39;: &#39;xxx&#39;})
}
</code></pre>
</li>
</ul>
<h2 id="-">小结</h2>
<p>图1： actions和mutations和state的关系图</p>
<p><img src="asset/vuex.png" alt="vuex"></p>
<p>图2：全天核心API小结</p>
<p><img src="asset/image-20210604084953510.png" alt="image-20210604084953510"></p>
<h2 id="-todos">改写todos</h2>
<ol>
<li>安装vuex，配置store</li>
<li><p>把TodoMain组件中的数据，从vuex从读出。</p>
</li>
<li><p>添加</p>
<p><img src="asset/image-20210929094114297.png" alt="image-20210929094114297"></p>
</li>
<li><p>删除</p>
<p>1.准备mutations，通过下标来删除(数组.splice(下标，1))</p>
<p>2.调用mutations</p>
</li>
<li><p>统计数量</p>
<p>1.准备getters</p>
</li>
<li><p>筛选</p>
<p><img src="asset/image-20210929102824675.png" alt="image-20210929102824675"></p>
</li>
</ol>
<p>7.清除已完成</p>
<p><img src="asset/image-20210929111941092.png" alt="image-20210929111941092"></p>
<p>8切换全选中/全不选中</p>
<p>9.本地存储</p>
<pre><code class="lang-js">watch: { //监听list改变时把数据存储在本地上
    // &#39;list&#39;
    // this.数据
    // this.计算属性
    // this.$route // this.$route.qeury.xxx

    &#39;$store.state.list&#39;: {
      deep:true,
      handler(newVal){
        localStorage.setItem(&#39;tododd&#39;,JSON.stringify(newVal))
      }
    }
  }
</code></pre>
<p><a href="https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/todos">https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/todos</a></p>
<h2 id="-">作业</h2>
<ol>
<li><p>默写画图，小结中的 图1，图2</p>
<p><img src="asset/image-20210928150511854.png" alt="image-20210928150511854"></p>
</li>
<li><p>操作 :<img src="asset/image-20210927152822203.png" alt="image-20210927152822203"></p>
</li>
<li><p>用vuex改写todos</p>
</li>
</ol>

          	</article>
        </div>
		</div>
  </body>
</html>
<script type="text/javascript" src="toc/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="toc/js/jquery.ztree.all-3.5.min.js"></script>
<script type="text/javascript" src="toc/js/ztree_toc.js"></script>
<script type="text/javascript" src="toc_conf.js"></script>

<SCRIPT type="text/javascript" >
<!--
$(document).ready(function(){
    var css_conf = eval(markdown_panel_style);
    $('#readme').css(css_conf)
    
    var conf = eval(jquery_ztree_toc_opts);
		$('#tree').ztree_toc(conf);
});
//-->
</SCRIPT>